
#include <map>
#include <BFont>
#include <BImage>
#include <BTexture>
#include <BEvent>
#include <BPainter>
#include "member_BWidget.h"
#include "member_BPainter.h"
#include "member_BImage.h"
#include "member_BFont.h"
#include "member_BCamera.h"
#include "member_BPixmap.h"
#include "member_BStyle.h"
#include "member_BTexture.h"
#include "IGlobal.h"

using namespace BWE;

#define member						(*(member_BPainter*)_ptr)
#define member_allocate()			_ptr = new member_BPainter(this)
#define member_release()			delete (member_BPainter*)_ptr

BPainter::BPainter(const BWidget* widget)
{
	member_allocate();
	member.save();

	member.widget = widget;
	member.size = widget_member(widget)->size;
	member.state = &widget_member(widget)->state;
	member.font = member.state->font;
	member.style = member.state->style;

	glBindFramebuffer(GL_FRAMEBUFFER, widget_member(widget)->fbo);

	setClip(member.size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

}
BPainter::BPainter(const BPixmap* pixmap)
{
	member_allocate();
	member.save();

	member.pixmap = pixmap;
	member.style = app_style;
	if (member.style)
		member.font = member.style->font();
	member.size = pixmap->size();

	setClip(member.size);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

}
BPainter::~BPainter()
{
	member.open();
	member_release();
}

const BWidget* BPainter::widget() const
{
	return member.widget;
}

void BPainter::setClip(int x, int y, int width, int height)
{
	setClip(BRect(x, y, width, height));
}
void BPainter::setClip(const BRect& clip)
{
	if (member.clip != clip)
	{
		member.clip = clip;
		glViewport(clip.x(), member.size.height() - clip.bottom(), clip.width(), clip.height());
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(clip.left() - 1, clip.right(), clip.bottom() + 1, clip.top(), -1, 1);
	}
}
const BRect& BPainter::clip() const
{
	return member.clip;
}

void BPainter::pushAttrib()
{
	glPushAttrib(GL_ALL_ATTRIB_BITS);
}
void BPainter::popAttrib()
{
	glPopAttrib();
}

void BPainter::pushMatrix()
{
	glPushMatrix();
}
void BPainter::popMatrix()
{
	glPopMatrix();
}

void BPainter::translate(float tx, float ty, float tz)
{
	glTranslatef(tx, ty, tz);
}
void BPainter::translate(const BPointf& pos, float tz)
{
	glTranslatef(pos.x(), pos.y(), tz);
}
void BPainter::rotate(float angle, float ax, float ay, float az)
{
	glRotatef(angle, ax, ay, az);
}
void BPainter::scale(float ratio, float ax, float ay, float az)
{
	glScalef(ratio * ax, ratio * ay, ratio * az);
}

void BPainter::translate(int tx, int ty, int tz)
{
	glTranslatef((float)tx, (float)ty, (float)tz);
}
void BPainter::translate(const BPoint& pos, int tz)
{
	glTranslatef((float)pos.x(), (float)pos.y(), (float)tz);
}
void BPainter::rotate(int angle, int ax, int ay, int az)
{
	glRotatef((float)angle, (float)ax, (float)ay, (float)az);
}
void BPainter::scale(int ratio, int ax, int ay, int az)
{
	glScalef((float)ratio * ax, (float)ratio * ay, (float)ratio * az);
}

bool BPainter::setColor(const BColor& color) const
{
	if (color.a() > 1)
	{
		member.color = color;
		glColor4ub(color.r(), color.g(), color.b(), color.a());
		return true;
	}
	return false;
}
bool BPainter::setColor(BByte r, BByte g, BByte b, BByte a) const
{
	if (a > 1)
	{
		member.color.set(r, g, b, a);
		glColor4ub(r, g, b, a);
		return true;
	}
	return false;
}
bool BPainter::setColor(StyleRole colorRole) const
{
	if (member.style == 0)
		return false;
	if(const BColor* color = member.findColor(colorRole))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}
bool BPainter::setColor(const char* colorName) const
{
	if (member.style == 0)
		return false;
	if (const BColor* color = member.findColor(colorName))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}
bool BPainter::setColor(const BString& colorName) const
{
	if (member.style == 0)
		return false;
	if (const BColor* color = member.findColor(colorName))
	{
		member.color = *color;
		glColor4ub(color->r(), color->g(), color->b(), color->a());
		return true;
	}
	return false;
}
const BColor& BPainter::color() const
{
	return member.color;
}

bool BPainter::bind(StyleRole imageRole)
{
	if (BImage* image = member.style->image(imageRole))
		return bind(image);
	return false;
}
bool BPainter::bind(const BTexture* texture)
{
	if (member.pixmap && member.pixmap == texture)
		return false;
	GLuint tbo = 0;
	if (texture && texture->enabled())
	{
		if (texture_member(texture)->dirty)
			texture->flush();
		tbo = texture_member(texture)->tbo;
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
			if (texture_member(texture)->blend == BTexture::Blend_Modulate)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
			if (texture_member(texture)->blend == BTexture::Blend_Replace)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
			if (texture_member(texture)->blend == BTexture::Blend_Decal)
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
			if (texture_member(texture)->blend == BTexture::Blend_Color)
			{
				const BColor& color = texture_member(texture)->blendColor;
				BColorf colorf(color.a() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f);
				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
				glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat*)&color);
			}
		}
		else
		{
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
bool BPainter::bind(const BWidget* widget)
{
	if (member.widget && member.widget == widget)
		return false;
	GLuint tbo = 0;
	if (widget)
	{
		tbo = widget_member(widget)->tbo;
		if (widget_member(widget)->dirty)
		{
			widget_member(widget)->frame();
		}
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
		}
		else
		{
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
bool BPainter::bind(const BCamera* camera)
{
	GLuint tbo = 0;
	if (camera)
	{
		tbo = camera_member(camera)->tbo;
	}
	if (member.tbo != tbo)
	{
		member.tbo = tbo;
		if (tbo)
		{
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, tbo);
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
		}
		else
		{
			glBindTexture(GL_TEXTURE_2D, 0);
			glDisable(GL_TEXTURE_2D);
		}
	}
	return member.tbo;
}
void BPainter::unbind()
{
	if (member.tbo)
	{
		member.tbo = 0;
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_TEXTURE_2D);
	}
}

void BPainter::setStyle(const BStyle* style)
{
	if (member.style != style)
	{
		member.style = style;
	}
}
const BStyle* BPainter::style() const
{
	return member.style;
}

void BPainter::setFont(const BFont* font)
{
	if (member.font != font)
	{
		member.font = font;
	}
}
const BFont* BPainter::font() const
{
	return member.font;
}

void BPainter::setPointSmooth(bool pointSmooth)
{
	if(pointSmooth)
	{
		glEnable(GL_POINT_SMOOTH);
	}
	else
	{
		glDisable(GL_POINT_SMOOTH);
	}
	member.pointSmooth = pointSmooth;
}
bool BPainter::pointSmooth() const
{
	return member.pointSmooth;
}

void BPainter::setPointSize(int size)
{
	if (member.pointSize != size)
	{
		member.pointSize = size;
		glPointSize((GLfloat)size);
	}
}
int BPainter::pointSize() const
{
	return member.pointSize;
}

void BPainter::setLineStipple(BUShort stipple)
{
	if (member.lineStipple != stipple)
	{
		member.lineStipple = stipple;
		if (stipple > 0)
		{
			glEnable(GL_LINE_STIPPLE);
			glLineStipple(1, stipple);
		}
		else
		{
			glDisable(GL_LINE_STIPPLE);
		}
	}
}
BUShort BPainter::stipple() const
{
	return member.lineStipple;
}

void BPainter::setLineSmooth(bool lineSmooth)
{
	if (member.lineSmooth != lineSmooth)
	{
		member.lineSmooth = lineSmooth;
		if (lineSmooth)
		{
			glEnable(GL_LINE_SMOOTH);
		}
		else
		{
			glDisable(GL_LINE_SMOOTH);
		}
	}
}
bool BPainter::lineSmooth() const
{
	return member.lineSmooth;
}

void BPainter::setLineWidth(int width)
{
	if (member.lineWidth != width)
	{
		member.lineWidth = width;
		glLineWidth((GLfloat)width);
	}
}
int BPainter::lineWidth() const
{
	return member.lineWidth;
}

void BPainter::drawPoint(int x, int y) const
{
	if(member.pointSize > 0)
	{
		glBegin(GL_POINTS);
			glVertex2i(x, y);
		glEnd();
	}
}
void BPainter::drawPoint(float x, float y) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2f(x, y);
		glEnd();
	}
}
void BPainter::drawPoint(double x, double y) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2d(x, y);
		glEnd();
	}
}

void BPainter::drawPoint(const BPoint& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2i(point.x(), point.y());
		glEnd();
	}
}
void BPainter::drawPoint(const BPointf& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2f(point.x(), point.y());
		glEnd();
	}
}
void BPainter::drawPoint(const BPointd& point) const
{
	if (member.pointSize > 0)
	{
		glBegin(GL_POINTS);
		glVertex2d(point.x(), point.y());
		glEnd();
	}
}

void BPainter::drawLine(int x0, int y0, int x1, int y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2i(x0, y0);
		glVertex2i(x1, y1);
		glEnd();
	}
}
void BPainter::drawLine(float x0, float y0, float x1, float y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glEnd();
	}
}
void BPainter::drawLine(double x0, double y0, double x1, double y1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2d(x0, y0);
		glVertex2d(x1, y1);
		glEnd();
	}
}

void BPainter::drawLine(const BPoint& p0, const BPoint& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glEnd();
	}
}
void BPainter::drawLine(const BPointf& p0, const BPointf& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glEnd();
	}
}
void BPainter::drawLine(const BPointd& p0, const BPointd& p1) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINES);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glEnd();
	}
}

void BPainter::drawLines(const BPoint* points, int size) const
{
	size /= 2;
	glBegin(GL_LINES);
	for(int i = 0; i < size; i++)
	{
		glVertex2i(points[i*2+0].x(), points[i*2+0].y());
		glVertex2i(points[i*2+1].x(), points[i*2+1].y());
	}
	glEnd();
}
void BPainter::drawLines(const BPointArray& points) const
{
	drawLines(points.data(), points.size());
}

void BPainter::drawLineLoop(const BPoint* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointf* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointd* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineLoop(const BPointArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointfArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineLoop(const BPointdArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_LOOP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineStrip(const BPoint* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointf* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointd* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawLineStrip(const BPointArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointfArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::drawLineStrip(const BPointdArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_LINE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2i(x0, y0);
		glVertex2i(x1, y1);
		glVertex2i(x2, y2);
		glEnd();
	}
}
void BPainter::drawTriangle(float x0, float y0, float x1, float y1, float x2, float y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2f(x0, y0);
		glVertex2f(x1, y1);
		glVertex2f(x2, y2);
		glEnd();
	}
}
void BPainter::drawTriangle(double x0, double y0, double x1, double y1, double x2, double y2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2d(x0, y0);
		glVertex2d(x1, y1);
		glVertex2d(x2, y2);
		glEnd();
	}
}

void BPainter::drawTriangle(const BPoint& p0, const BPoint& p1, const BPoint& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glEnd();
	}
}
void BPainter::drawTriangle(const BPointf& p0, const BPointf& p1, const BPointf& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glEnd();
	}
}
void BPainter::drawTriangle(const BPointd& p0, const BPointd& p1, const BPointd& p2) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glEnd();
	}
}

void BPainter::fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2i(x0, y0);
	glVertex2i(x1, y1);
	glVertex2i(x2, y2);
	glEnd();
}
void BPainter::fillTriangle(float x0, float y0, float x1, float y1, float x2, float y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2f(x0, y0);
	glVertex2f(x1, y1);
	glVertex2f(x2, y2);
	glEnd();
}
void BPainter::fillTriangle(double x0, double y0, double x1, double y1, double x2, double y2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2d(x0, y0);
	glVertex2d(x1, y1);
	glVertex2d(x2, y2);
	glEnd();
}

void BPainter::fillTriangle(const BPoint& p0, const BPoint& p1, const BPoint& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2i(p0.x(), p0.y());
	glVertex2i(p1.x(), p1.y());
	glVertex2i(p2.x(), p2.y());
	glEnd();
}
void BPainter::fillTriangle(const BPointf& p0, const BPointf& p1, const BPointf& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2f(p0.x(), p0.y());
	glVertex2f(p1.x(), p1.y());
	glVertex2f(p2.x(), p2.y());
	glEnd();
}
void BPainter::fillTriangle(const BPointd& p0, const BPointd& p1, const BPointd& p2) const
{
	glBegin(GL_TRIANGLES);
	glVertex2d(p0.x(), p0.y());
	glVertex2d(p1.x(), p1.y());
	glVertex2d(p2.x(), p2.y());
	glEnd();
}

void BPainter::drawTriangles(const BPoint* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPoint& p0 = points[i];
			const BPoint& p1 = points[i + 1];
			const BPoint& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointf* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPointf& p0 = points[i];
			const BPointf& p1 = points[i + 1];
			const BPointf& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointd* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < size; i += 3)
		{
			const BPointd& p0 = points[i];
			const BPointd& p1 = points[i + 1];
			const BPointd& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::drawTriangles(const BPointArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPoint& p0 = points[i];
			const BPoint& p1 = points[i + 1];
			const BPoint& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointfArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPointf& p0 = points[i];
			const BPointf& p1 = points[i + 1];
			const BPointf& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangles(const BPointdArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 0; i < points.size(); i += 3)
		{
			const BPointd& p0 = points[i];
			const BPointd& p1 = points[i + 1];
			const BPointd& p2 = points[i + 2];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::fillTriangles(const BPoint* points, int size) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPoint& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointf* points, int size) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointd* points, int size) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < size; i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::fillTriangles(const BPointArray& points) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2i(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointfArray& points) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2f(points[i].x(), points[i].y());
		}
		glEnd();
	}
}
void BPainter::fillTriangles(const BPointdArray& points) const
{
	if (member.lineWidth > 0)
	{
		glBegin(GL_TRIANGLES);
		for (int i = 0; i < points.size(); i++)
		{
			glVertex2d(points[i].x(), points[i].y());
		}
		glEnd();
	}
}

void BPainter::drawTriangleStrip(const BPoint* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPoint& p0 = points[i - 2];
			const BPoint& p1 = points[i - 1];
			const BPoint& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointf* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPointf& p0 = points[i - 2];
			const BPointf& p1 = points[i - 1];
			const BPointf& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointd* points, int size) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < size; i++)
		{
			const BPointd& p0 = points[i - 2];
			const BPointd& p1 = points[i - 1];
			const BPointd& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::drawTriangleStrip(const BPointArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPoint& p0 = points[i - 2];
			const BPoint& p1 = points[i - 1];
			const BPoint& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2i(p0.x(), p0.y());
			glVertex2i(p1.x(), p1.y());
			glVertex2i(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointfArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPointf& p0 = points[i - 2];
			const BPointf& p1 = points[i - 1];
			const BPointf& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2f(p0.x(), p0.y());
			glVertex2f(p1.x(), p1.y());
			glVertex2f(p2.x(), p2.y());
			glEnd();
		}
	}
}
void BPainter::drawTriangleStrip(const BPointdArray& points) const
{
	if (member.lineWidth > 0)
	{
		for (int i = 2; i < points.size(); i++)
		{
			const BPointd& p0 = points[i - 2];
			const BPointd& p1 = points[i - 1];
			const BPointd& p2 = points[i];
			glBegin(GL_LINE_LOOP);
			glVertex2d(p0.x(), p0.y());
			glVertex2d(p1.x(), p1.y());
			glVertex2d(p2.x(), p2.y());
			glEnd();
		}
	}
}

void BPainter::fillTriangleStrip(const BPoint* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPoint& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointf* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointd* points, int size) const
{
	if (size > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < size; i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::fillTriangleStrip(const BPointArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPoint& p = points[i];
			glVertex2i(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointfArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointf& p = points[i];
			glVertex2f(p.x(), p.y());
		}
		glEnd();
	}
}
void BPainter::fillTriangleStrip(const BPointdArray& points) const
{
	if (points.size() > 2)
	{
		glBegin(GL_TRIANGLE_STRIP);
		for (int i = 0; i < points.size(); i++)
		{
			const BPointd& p = points[i];
			glVertex2d(p.x(), p.y());
		}
		glEnd();
	}
}

void BPainter::drawRect(const BRect& rect) const
{
	drawRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::drawRect(const BPoint& pos, const BSize& size) const
{
	drawRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::drawRect(int x, int y, int width, int height) const
{
	if(member.lineWidth > 0)
	{
		glBegin(GL_LINE_LOOP);
			glVertex2i(x, y);
			glVertex2i(x, y + height);
			glVertex2i(x + width, y + height);
			glVertex2i(x + width, y);
		glEnd();
	}
}

void BPainter::fillRect(const BRect& rect) const
{
	fillRect(rect.x(), rect.y(), rect.width(), rect.height());
}
void BPainter::fillRect(const BPoint& pos, const BSize& size) const
{
	fillRect(pos.x(), pos.y(), size.width(), size.height());
}
void BPainter::fillRect(int x, int y, int width, int height) const
{
	if (width < 1 || height < 1)
		return;
	if (member.tbo)
	{
		glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(x, y);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(x, y + height);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(x + width, y + height);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(x + width, y);
		glEnd();
	}
	else
	{
		glBegin(GL_QUADS);
			glVertex2i(x, y);
			glVertex2i(x, y + height);
			glVertex2i(x + width, y + height);
			glVertex2i(x + width, y);
		glEnd();
	}
}

void BPainter::drawRoundRect(const BRect& rect, int rx, int ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, (float)rx, (float)ry);
	drawLineLoop(member.points);
	
}
void BPainter::drawRoundRect(const BPoint& pos, const BSize& size, int rx, int ry) const
{
	drawRoundRect(BRect(pos, size), rx, ry);
}
void BPainter::drawRoundRect(int x, int y, int width, int height, int rx, int ry) const
{
	drawRoundRect(BRect(x, y, width, height), rx, ry);
}

void BPainter::fillRoundRect(const BRect& rect, int rx, int ry) const
{
	if (rx < 1)
		return;
	if (ry < 0)
		ry = rx;
	member.createPoints(rect, (float)rx, (float)ry);
	fillPolygon(member.points);
}
void BPainter::fillRoundRect(const BPoint& pos, const BSize& size, int rx, int ry) const
{
	fillRoundRect(BRect(pos, size), rx, ry);
}
void BPainter::fillRoundRect(int x, int y, int width, int height, int rx, int ry) const
{
	fillRoundRect(BRect(x, y, width, height), rx, ry);
}

void BPainter::drawQuad(const BPoint& p0, const BPoint& p1, const BPoint& p2, const BPoint& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
	glEnd();
}
void BPainter::drawQuad(const BPointf& p0, const BPointf& p1, const BPointf& p2, const BPointf& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
	glEnd();
}
void BPainter::drawQuad(const BPointd& p0, const BPointd& p1, const BPointd& p2, const BPointd& p3) const
{
	glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
	glEnd();
}

void BPainter::fillQuad(const BPoint& p0, const BPoint& p1, const BPoint& p2, const BPoint& p3) const
{
	glBegin(GL_QUADS);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
	glEnd();
}
void BPainter::fillQuad(const BPointf& p0, const BPointf& p1, const BPointf& p2, const BPointf& p3) const
{
	glBegin(GL_QUADS);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
	glEnd();
}
void BPainter::fillQuad(const BPointd& p0, const BPointd& p1, const BPointd& p2, const BPointd& p3) const
{
	glBegin(GL_QUADS);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
	glEnd();
}

void BPainter::drawQuads(const BPoint* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i+= 4)
	{
		const BPoint& p0 = points[i];
		const BPoint& p1 = points[i + 1];
		const BPoint& p2 = points[i + 2];
		const BPoint& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointf* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointf& p0 = points[i];
		const BPointf& p1 = points[i + 1];
		const BPointf& p2 = points[i + 2];
		const BPointf& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointd* points, int size)
{
	size -= 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointd& p0 = points[i];
		const BPointd& p1 = points[i + 1];
		const BPointd& p2 = points[i + 2];
		const BPointd& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
		glEnd();
	}
}

void BPainter::drawQuads(const BPointArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPoint& p0 = points[i];
		const BPoint& p1 = points[i + 1];
		const BPoint& p2 = points[i + 2];
		const BPoint& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2i(p0.x(), p0.y());
		glVertex2i(p1.x(), p1.y());
		glVertex2i(p2.x(), p2.y());
		glVertex2i(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointfArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointf& p0 = points[i];
		const BPointf& p1 = points[i + 1];
		const BPointf& p2 = points[i + 2];
		const BPointf& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2f(p0.x(), p0.y());
		glVertex2f(p1.x(), p1.y());
		glVertex2f(p2.x(), p2.y());
		glVertex2f(p3.x(), p3.y());
		glEnd();
	}
}
void BPainter::drawQuads(const BPointdArray& points)
{
	int size = points.size() - 4;
	if (size < 0)
		return;
	for (int i = 0; i < size; i += 4)
	{
		const BPointd& p0 = points[i];
		const BPointd& p1 = points[i + 1];
		const BPointd& p2 = points[i + 2];
		const BPointd& p3 = points[i + 3];
		glBegin(GL_LINE_LOOP);
		glVertex2d(p0.x(), p0.y());
		glVertex2d(p1.x(), p1.y());
		glVertex2d(p2.x(), p2.y());
		glVertex2d(p3.x(), p3.y());
		glEnd();
	}
}

void BPainter::fillQuads(const BPoint* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPoint& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointf* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointd* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuads(const BPointArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPoint& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointfArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuads(const BPointdArray& points)
{
	int size = points.size() - 3;
	if (size < 0)
		return;
	glBegin(GL_QUADS);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuadStrip(const BPoint* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPoint& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointf* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointd* points, int size)
{
	if (size < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < size; i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::fillQuadStrip(const BPointArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPoint& p = points[i];
		glVertex2i(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointfArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPointf& p = points[i];
		glVertex2f(p.x(), p.y());
	}
	glEnd();
}
void BPainter::fillQuadStrip(const BPointdArray& points)
{
	if (points.size() < 4)
		return;
	glBegin(GL_QUAD_STRIP);
	for (int i = 0; i < points.size(); i++)
	{
		const BPointd& p = points[i];
		glVertex2d(p.x(), p.y());
	}
	glEnd();
}

void BPainter::drawEllipse(const BPoint& center, int radiusX, int radiusY) const
{
	float rx2 = (float)radiusX * radiusX;
	float ry2 = (float)radiusY * radiusY;
	glBegin(GL_LINE_LOOP);
	for (int x = radiusX; x > -radiusX; x -= 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() + y);
	}
	for (int x = -radiusX; x <= radiusX; x += 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() - y);
	}
	glEnd();
}
void BPainter::drawEllipse(int x, int y, int width, int height) const
{
	int hw = width / 2;
	int hh = height / 2;
	drawEllipse(BPoint(x + hw, y + hh), hw, hh);
}
void BPainter::drawEllipse(const BPoint& pos, const BSize& size) const
{
	int hw = size.width() / 2;
	int hh = size.height() / 2;
	drawEllipse(pos + BPoint(hw, hh), hw, hh);
}
void BPainter::drawEllipse(const BRect& rect) const
{
	drawEllipse(rect.center(), rect.width() / 2, rect.height() / 2);
}

void BPainter::fillEllipse(const BPoint& center, int radiusX, int radiusY) const
{
	float rx2 = (float)radiusX * radiusX;
	float ry2 = (float)radiusY * radiusY;
	glBegin(GL_POLYGON);
	for (int x = radiusX; x > -radiusX; x -= 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() + y);
	}
	for (int x = -radiusX; x <= radiusX; x += 3)
	{
		float y = sqrt((1 - (x * x) / rx2) * ry2);
		glVertex2f(center.x() + (float)x, center.y() - y);
	}
	glEnd();
}
void BPainter::fillEllipse(int x, int y, int width, int height) const
{
	int hw = width / 2;
	int hh = height / 2;
	fillEllipse(BPoint(x + hw, y + hh), hw, hh);
}
void BPainter::fillEllipse(const BPoint& pos, const BSize& size) const
{
	int hw = size.width() / 2;
	int hh = size.height() / 2;
	fillEllipse(pos + BPoint(hw, hh), hw, hh);
}
void BPainter::fillEllipse(const BRect& rect) const
{
	fillEllipse(rect.center(), rect.width() / 2, rect.height() / 2);
}

void BPainter::drawPolygon(const BPoint* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < size; i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::drawPolygon(const BPointArray& points) const
{
	if (points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_LINE_LOOP);
	for(int i = 0; i < points.size(); i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPoint* points, int size) const
{
	if (!points || size < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for (int i = 0; i < size; i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}
void BPainter::fillPolygon(const BPointArray& points) const
{
	if(points.size() < 3 || member.lineWidth < 1)
		return;
	glBegin(GL_POLYGON);
	for(int i = 0; i < points.size(); i++)
	{
		glVertex2i(points[i].x(), points[i].y());
	}
	glEnd();
}

void BPainter::drawCircle(int cx, int cy, int radius, int sides) const
{
	glEnable(GL_POLYGON_SMOOTH);
	glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
	if (sides < 3)
		sides = bLimit(radius, 6, 24);
	float sr = PI2f / sides;
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < sides; i++)
	{
		float angle = i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
	glDisable(GL_POLYGON_SMOOTH);
}
void BPainter::drawCircle(const BPoint& center, int radius, int sides) const
{
	drawCircle(center.x(), center.y(), radius, sides);
}
void BPainter::fillCircle(int cx, int cy, int radius, int sides) const
{
	if (sides < 3)
		sides = bLimit(radius, 6, 24);
	float sr = PI2f / sides;
	glBegin(GL_POLYGON);
	for (int i = 0; i < sides; i++)
	{
		float angle = i * sr;
		float x = cos(angle) * radius;
		float y = sin(angle) * radius;
		glVertex2f(cx + x, cy + y);
	}
	glEnd();
}
void BPainter::fillCircle(const BPoint& center, int radius, int sides) const
{
	fillCircle(center.x(), center.y(), radius, sides);
}

void BPainter::drawText(const BPoint& pos, const BString& text, Align align)
{
	drawText(pos.x(), pos.y(), text, align);
}
void BPainter::drawText(int x, int y, const BString& text, Align align)
{
	if (text.empty() || !member.font)
		return;

	const BFont* font = member.font;
	if(align)
	{
		BSize textSize = font->textSize(text);
		if (align & Align_Right)
			x -= textSize.width();
		if (align & Align_Bottom)
			y -= textSize.height();
		if (align & Align_HCenter)
			x -= textSize.width() / 2;
		if (align & Align_VCenter)
			y -= textSize.height() / 2;
	}

	unbind();
	glEnable(GL_TEXTURE_2D);

	int fontHeight = font->size();
	int posX = x;
	int posY = (int)(y - fontHeight * 0.2);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + member.clip.bottom())
			break;

		BCode code = cit.code();
		BSize codeSize = member.font->codeSize(code);

		if (code == '\n')//new line.
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (code == '\t')
		{
			int times = (posX - x) / codeSize.width() + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(code);
		if (info && info->image)
		{
			const BImage* image = info->image;
			int left = info->left;
			int top = info->top;

			int bX = posX + left;
			int bY = posY + fontHeight - top;
			int bW = image->width();
			int bH = image->height();

			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(bX, bY);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(bX, bY + bH);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(bX + bW, bY + bH);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(bX + bW, bY);
			glEnd();
		}
		else
		{
			drawRect(posX, posY, codeSize.width(), codeSize.height());
		}
		posX += codeSize.width();
		if (posX > member.clip.right())
		{
			while (cit.valid() && *cit != '\n')
				++cit;
		}
	}
	glDisable(GL_TEXTURE_2D);
}

void BPainter::drawText(const BRect& rect, const BString& text, bool lineWrap)
{
	if (rect.empty() || text.empty())
		return;
	drawText(rect.x(), rect.y(), rect.width(), rect.height(), text, lineWrap);
}
void BPainter::drawText(const BPoint& pos, const BSize& size, const BString& text, bool lineWrap)
{
	if (size.empty() || text.empty())
		return;
	drawText(pos.x(), pos.y(), size.width(), size.height(), text, lineWrap);
}
void BPainter::drawText(int x, int y, int width, int height, const BString& text, bool lineWrap)
{
	if (text.empty() || !member.font)
		return;
	unbind();
	glEnable(GL_TEXTURE_2D);
	const BFont* font = member.font;
	int fontHeight = font->size();
	int posX = x;
	int posY = y - (int)(fontHeight * 0.2);
	for (BString::const_iterator cit = text.begin(); cit != text.end(); cit++)
	{
		if (posY > y + height)
			break;
		BCode code = cit.code();
		BSize codeSize = member.font->codeSize(code);
		if (code == '\n')
		{
			posX = x;
			posY += fontHeight;
			continue;
		}
		if (code == '\t')
		{
			int times = (posX - x) / codeSize.width() + 1;
			posX = times * codeSize.width() + x;
			continue;
		}
		CodeInfo* info = font_member(font)->getCodeInfo(code);
		if (info && info->image)
		{
			const BImage* image = info->image;
			int left = info->left;
			int top = info->top;

			int bX = posX + left;
			int bY = posY + fontHeight - top;
			int bW = image->width();
			int bH = image->height();

			if (texture_member(image)->dirty)
				image->flush();
			glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(bX, bY);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(bX, bY + bH);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(bX + bW, bY + bH);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(bX + bW, bY);
			glEnd();
		}
		if (posX + codeSize.width() > x + width)
		{
			if (!lineWrap)
			{
				while (cit.valid() && *cit != '\n')
					++cit;
			}
			posX = x;
			posY += fontHeight;
		}
		posX += codeSize.width();
	}
	glDisable(GL_TEXTURE_2D);
}

void BPainter::drawText(const BRect& rect, const BString& text, Align align, bool lineWrap)
{
	if (text.empty() || !member.font)
		return;
	const BFont* font = member.font;
	BSize textSize = font->textSize(text);
	BRect textRect = rect.align(align, textSize);
	if(!text.contain('\n'))
	{
		drawText(textRect.x(), textRect.y(), textRect.width(), textRect.height(), text);
		return;
	}
	int fontHeight = font->size();
	int x = textRect.x();
	int y = textRect.y();
	unbind();
	glEnable(GL_TEXTURE_2D);
	int pos = 0;
	BString line;
	while(pos < text.size())
	{
		pos = text.line(line, pos);
		int posX = x;
		int posY = y - (int)(fontHeight * 0.2);
		if (posY > y + fontHeight)
			break;
		int width = font->textSize(line).width();
		if (align & Align_HCenter)
			posX = x + (textRect.width() - width) / 2;
		if (align & Align_Right)
			posX = x + textRect.width() - width;
		for (BString::const_iterator cit = line.begin(); cit != line.end(); cit++)
		{
			BCode code = cit.code();
			BSize codeSize = member.font->codeSize(code);
			if (code == '\t')
			{
				int times = (posX - x) / codeSize.width() + 1;
				posX = times * codeSize.width() + x;
				continue;
			}
			CodeInfo* info = font_member(font)->getCodeInfo(code);
			if (info && info->image)
			{
				const BImage* image = info->image;
				int left = info->left;
				int top = info->top;

				int bX = posX + left;
				int bY = posY + fontHeight - top;
				int bW = image->width();
				int bH = image->height();

				if (texture_member(image)->dirty)
					image->flush();
				glBindTexture(GL_TEXTURE_2D, texture_member(image)->tbo);
				glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f);		glVertex2i(bX, bY);
				glTexCoord2f(0.0f, 1.0f);		glVertex2i(bX, bY + bH);
				glTexCoord2f(1.0f, 1.0f);		glVertex2i(bX + bW, bY + bH);
				glTexCoord2f(1.0f, 0.0f);		glVertex2i(bX + bW, bY);
				glEnd();
			}
			if (posX + codeSize.width() > textRect.right())
			{
				break;
			}
			posX += codeSize.width();
		}
		y += fontHeight;
	}
	glDisable(GL_TEXTURE_2D);
}
void BPainter::drawText(const BPoint& pos, const BSize& size, const BString& text, Align align, bool lineWrap)
{
	drawText(BRect(pos, size), text, align, lineWrap);
}
void BPainter::drawText(int x, int y, int width, int height, const BString& text, Align align, bool lineWrap)
{
	drawText(BRect(x, y, width, height), text, align, lineWrap);
}

void BPainter::drawImage(const BPoint& pos, const BImage* image, Align align)
{
	drawImage(pos.x(), pos.y(), image, align);
}
void BPainter::drawImage(int x, int y, const BImage* image, Align align)
{
	if (!image)
		return;

	BSize size = image->size();
	if (align)
	{
		if (align & Align_Right)
			x -= size.width();
		if (align & Align_Bottom)
			y -= size.height();
		if (align & Align_HCenter)
			x -= size.width() / 2;
		if (align & Align_VCenter)
			y -= size.height() / 2;
	}

	drawImage(x, y, size.width(), size.height(), image, false);
}

void BPainter::drawImage(const BRect& rect, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSize imageSize = rect.size().wrap(image->size());
			BRect imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(imageRect.left(), imageRect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(imageRect.left(), imageRect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(imageRect.right(), imageRect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(imageRect.right(), imageRect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(rect.right(), rect.top());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BPoint& pos, const BSize& size, const BImage* image, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, wrapped);
}
void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, bool wrapped)
{
	if (bind(image))
	{
		if (wrapped)
		{
			BSize imageSize = BSize(width, height).wrap(image->size());
			BRect rect = BRect(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(rect.left(), rect.top());
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(rect.left(), rect.bottom());
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(rect.right(), rect.bottom());
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(rect.right(), rect.top());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(0.0f, 0.0f);		glVertex2i(x, y);
			glTexCoord2f(0.0f, 1.0f);		glVertex2i(x, y + height);
			glTexCoord2f(1.0f, 1.0f);		glVertex2i(x + width, y + height);
			glTexCoord2f(1.0f, 0.0f);		glVertex2i(x + width, y);
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawImage(const BRect& rect, const BImage* image, const BRect& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / image->width();
		float rh = 1.0f / image->height();
		float tx0 = area.left() * rw;
		float tx1 = area.right() * rw;
		float ty0 = area.top() * rh;
		float ty1 = area.bottom() * rh;
		if (wrapped)
		{
			BSize imageSize = rect.size().wrap(area.size());
			BRect imageRect = rect.align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2i(imageRect.x(), imageRect.y());
			glTexCoord2f(tx0, ty1);		glVertex2i(imageRect.x(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty1);		glVertex2i(imageRect.x() + imageRect.width(), imageRect.y() + imageRect.height());
			glTexCoord2f(tx1, ty0);		glVertex2i(imageRect.x() + imageRect.width(), imageRect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(tx0, ty0);		glVertex2i(rect.x(), rect.y());
			glTexCoord2f(tx0, ty1);		glVertex2i(rect.x(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty1);		glVertex2i(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(tx1, ty0);		glVertex2i(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		unbind();
	}
}
void BPainter::drawImage(const BPoint& pos, const BSize& size, const BImage* image, const BRect& area, bool wrapped)
{
	drawImage(pos.x(), pos.y(), size.width(), size.height(), image, area, wrapped);
}
void BPainter::drawImage(int x, int y, int width, int height, const BImage* image, const BRect& area, bool wrapped)
{
	if (bind(image))
	{
		float rw = 1.0f / area.width();
		float rh = 1.0f / area.height();
		if (wrapped)
		{
			BSize imageSize = BSize(width, height).wrap(image->size());
			BRect rect = BRect(x, y, width, height).align(Align_Center, imageSize);
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2i(rect.x(), rect.y());
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2i(rect.x(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2i(rect.x() + rect.width(), rect.y() + rect.height());
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2i(rect.x() + rect.width(), rect.y());
			glEnd();
		}
		else
		{
			glBegin(GL_QUADS);
			glTexCoord2f(area.left() * rw, area.top() * rh);		glVertex2i(x, y);
			glTexCoord2f(area.left() * rw, area.bottom() * rh);		glVertex2i(x, y + height);
			glTexCoord2f(area.right() * rw, area.bottom() * rh);	glVertex2i(x + width, y + height);
			glTexCoord2f(area.right() * rw, area.top() * rh);		glVertex2i(x + width, y);
			glEnd();
		}
		unbind();
	}
}

void BPainter::drawGraph(int x, int y, int width, int height, Graph graph)
{
	BRect rect(x, y, width, height);
	drawGraph(rect, graph);
}
void BPainter::drawGraph(const BRect& rect, Graph graph)
{
	if (graph == Graph_None)
		return;
	float x = (float)rect.x();
	float y = (float)rect.y();
	float w = (float)rect.width();
	float h = (float)rect.height();
	switch (graph)
	{
	case Graph_None:
		break;
	case Graph_Circle:
	{
		int radius = bMin(rect.width(), rect.height());
		drawCircle(rect.center(), radius / 2);
		break;
	}
	case Graph_Circle_Fill:
	{
		int radius = bMin(rect.width(), rect.height());
		fillCircle(rect.center(), radius / 2);
		break;
	}
	case Graph_Square:
	{
		drawRect(rect);
		break;
	}
	case Graph_Square_Fill:
	{
		fillRect(rect);
		break;
	}
	case Graph_Arrow_Up:
	{
		BPointf p1(x + w / 2, y);
		BPointf p0(x, y + h);
		BPointf p2(x + w, y + h);
		drawTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Up_Fill:
	{
		BPointf p1(x + w / 2, y);
		BPointf p0(x, y + h);
		BPointf p2(x + w, y + h);
		fillTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Down:
	{
		BPointf p0(x, y);
		BPointf p1(x + w / 2, y + h);
		BPointf p2(x + w, y);
		drawTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Down_Fill:
	{
		BPointf p0(x, y);
		BPointf p1(x + w / 2, y + h);
		BPointf p2(x + w, y);
		fillTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Left:
	{
		BPointf p0(x + w, y);
		BPointf p1(x, y + h / 2);
		BPointf p2(x + w, y + h);
		drawTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Left_Fill:
	{
		BPointf p0(x, y + h / 2);
		BPointf p1(x + w, y + h);
		BPointf p2(x + w, y);
		fillTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Right:
	{
		BPointf p0(x, y);
		BPointf p1(x, y + h);
		BPointf p2(x + w, y + h / 2);
		drawTriangle(p0, p1, p2);
		break;
	}
	case Graph_Arrow_Right_Fill:
	{
		BPointf p0(x, y);
		BPointf p1(x, y + h);
		BPointf p2(x + w, y + h / 2);
		fillTriangle(p0, p1, p2);
		break;
	}
	case Graph_Plus:
	{
		BPointf p1(x + w / 2, y);
		BPointf p0(x + w / 2, y + h);
		BPointf p2(x, y + h / 2);
		BPointf p3(x + w, y + h / 2);
		drawLine(p0, p1);
		drawLine(p2, p3);
		break;
	}
	case Graph_Minus:
	{
		BPointf p0(x, y + h / 2);
		BPointf p1(x + w, y + h / 2);
		drawLine(p0, p1);
		break;
	}
	case Graph_Check:
	{
		BPointf p0 = rect.leftTop() + BPointf(0, h / 2);
		BPointf p1 = rect.leftBottom() + BPointf(w / 2, 0);
		BPointf p2 = rect.rightTop();
		drawLine(p0, p1);
		drawLine(p1, p2);
		break;
	}
	case Graph_Radio:
	{
		int radius = bMin(rect.width(), rect.height());
		this->setLineSmooth(true);
		drawCircle(rect.center(), radius / 2);
		fillCircle(rect.center(), radius / 3);
		break;
	}
	case Graph_Cross:
	{
		drawLine(rect.leftTop(), rect.rightBottom());
		drawLine(rect.leftBottom(), rect.rightTop());
		break;
	}
	case Graph_Minimize:
	{
		BRect minRect = rect % 50;
		drawLine(minRect.leftBottom(), minRect.rightBottom());
		break;
	}
	case Graph_Maximize:
	{
		BRect maxRect = rect % 60;
		drawRect(maxRect);
		break;
	}
	case Graph_Normalize:
	{
		BRect maxRect = rect % 50;
		drawRect(maxRect);
		break;
	}
	default:
		break;
	}
}

void BPainter::drawBackground(State state, bool checked)
{
	if (!member.widget || !member.style)
		return;

	if (!member.state->enabled)
		state = State_Disable;
	if (!state && member.state->actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	StyleRole colorRole = Style_None;
	StyleRole imageRole = Style_None;
	switch (state)
	{
	case State_Normal:
		colorRole = Color_Background;
		imageRole = Image_Background;
		break;
	case State_Actived:
		colorRole = Color_Background_Actived;
		imageRole = Image_Background_Actived;
		break;
	case State_Hovered:
		colorRole = Color_Background_Hovered;
		imageRole = Image_Background_Hovered;
		break;
	case State_Pressed:
		colorRole = Color_Background_Pressed;
		imageRole = Image_Background_Pressed;
		break;
	case State_Disable:
		colorRole = Color_Background_Disable;
		imageRole = Image_Background_Disable;
		break;
	default:
		return;
	}
	if (checked)
	{
		colorRole = Color_Background_Checked;
		imageRole = Image_Background_Checked;
	}
	if (!setColor(colorRole))
		return;
	int border = member.widget->border();
	BRect bgRect = member.widget->size();
	bgRect.left() += border;
	bgRect.right() -= border;
	bgRect.top() += border;
	bgRect.bottom() -= border;
	if (IRound* round = widget_member(member.widget)->round)
	{
		if (BImage* image = member.style->image(imageRole))
			drawImage(bgRect, image);
		else
		{
			glBegin(GL_TRIANGLE_FAN);
			for (int i = 0; i < round->backgroundPoints.size(); i++)
			{
				const BPointf& p = round->backgroundPoints[i];
				glVertex2f(p.x(), p.y());
			}
			glEnd();
		}
	}
	else
	{
		if (BImage* image = member.style->image(imageRole))
			drawImage(bgRect, image);
		else
			fillRect(bgRect);
	}
}
void BPainter::drawPerch(State state, bool checked)
{
	if (!member.widget || !member.style)
		return;

	if (!member.state->enabled)
		state = State_Disable;
	if (!state && member.state->actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	const BPerch& perch = widget_member(member.widget)->perch;
	if (perch == BPerch())
		return;

	StyleRole colorRole = Style_None;
	switch (state)
	{
	case State_Normal:
		colorRole = Color_Perch;
		break;
	case State_Actived:
		colorRole = Color_Perch_Actived;
		break;
	case State_Hovered:
		colorRole = Color_Perch_Hovered;
		break;
	case State_Pressed:
		colorRole = Color_Perch_Pressed;
		break;
	case State_Disable:
		colorRole = Color_Perch_Disable;
		break;
	default:
		return;
	}
	if (checked)
	{
		colorRole = Color_Perch_Checked;
	}
	if (!setColor(colorRole))
		return;

	member_BWidget* wm = widget_member(member.widget);
	int b = wm->border;
	int w = wm->size.width();
	int h = wm->size.height();

	const BRect& topRect = wm->rectTop;
	const BRect& leftRect = wm->rectLeft;
	const BRect& rightRect = wm->rectRight;
	const BRect& bottomRect = wm->rectBottom;

	BRect leftTopRect(b, b, perch.left(), perch.top());
	BRect leftBottomRect(b, bottomRect.top(), perch.left(), perch.bottom());
	BRect rightTopRect(rightRect.left(), b, perch.right(), perch.top());
	BRect rightBottomRect(rightRect.left(), bottomRect.top(), perch.right(), perch.bottom());
	if (IRound* round = widget_member(member.widget)->round)
	{
		fillTriangles(round->perchPoints);
	}
	else
	{
		fillRect(leftRect);
		fillRect(topRect);
		fillRect(rightRect);
		fillRect(bottomRect);

		fillRect(leftTopRect);
		fillRect(leftBottomRect);
		fillRect(rightTopRect);
		fillRect(rightBottomRect);
	}
}
void BPainter::drawMargin(State state, bool checked)
{
	if (!member.widget || !member.style)
		return;

	if (!member.state->enabled)
		state = State_Disable;
	if (!state && member.state->actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	const BMargin& margin = member.widget->margin();
	if (margin == BMargin())
		return;

	StyleRole colorRole = Style_None;
	switch (state)
	{
	case State_Normal:
		colorRole = Color_Margin;
		break;
	case State_Actived:
		colorRole = Color_Margin_Actived;
		break;
	case State_Hovered:
		colorRole = Color_Margin_Hovered;
		break;
	case State_Pressed:
		colorRole = Color_Margin_Pressed;
		break;
	case State_Disable:
		colorRole = Color_Margin_Disable;
		break;
	default:
		return;
	}
	if (checked)
	{
		colorRole = Color_Margin_Checked;
	}
	if (!setColor(colorRole))
		return;

	int b = member.widget->border();
	int w = member.widget->width();
	int h = member.widget->height();

	const BPerch& perch = member.widget->perch();
	int pleft = perch.left();
	int pright = perch.right();
	int ptop = perch.top();
	int pbottom = perch.bottom();

	int mleft = margin.left();
	int mright = margin.right();
	int mtop = margin.top();
	int mbottom = margin.bottom();

	BRect left_rect(b + pleft, b + ptop, mleft, h - b - b - ptop - pbottom);
	BRect top_rect(b + pleft, b + ptop, w - b - b - pleft - pright, mtop);
	BRect right_rect(w - b - pright - mright, b + ptop + mtop, mright, h - b - b - ptop - mtop - pbottom);
	BRect bottom_rect(b + pleft, h - b - pbottom - mbottom, w - b - b - pleft - pright, mbottom);
	BRect left_top_rect(left_rect.x(), top_rect.y(), mleft, mtop);
	BRect left_bottom_rect(left_rect.x(), bottom_rect.y(), mleft, mbottom);
	BRect right_top_rect(right_rect.x(), top_rect.y(), mright, mtop);
	BRect right_bottom_rect(right_rect.x(), bottom_rect.y(), mright, mtop);

	if (IRound* round = widget_member(member.widget)->round)
	{
		//glEnable(GL_POLYGON_SMOOTH);
		fillTriangles(round->marginPoints);
		//glDisable(GL_POLYGON_SMOOTH);
	}
	else
	{
		if (mleft > 0)
		{
			fillRect(left_rect);
		}
		if (mtop > 0)
		{
			fillRect(top_rect);
		}
		if (mright > 0)
		{
			fillRect(right_rect);
		}
		if (mbottom > 0)
		{
			fillRect(bottom_rect);
		}
		if (left_top_rect.valid())
		{
			fillRect(left_top_rect);
		}
		if (left_bottom_rect.valid())
		{
			fillRect(left_bottom_rect);
		}
		if (right_top_rect.valid())
		{
			fillRect(right_top_rect);
		}
		if (right_bottom_rect.valid())
		{
			fillRect(right_bottom_rect);
		}
	}
}
void BPainter::drawBorder(State state, bool checked)
{
	if (!member.widget || !member.style)
		return;

	int b = member.widget->border();
	if (b < 1)
		return;

	if (!member.state->enabled)
		state = State_Disable;
	if (!state && member.state->actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	StyleRole colorRole = Style_None;
	switch (state)
	{
	case State_Normal:
		colorRole = Color_Border;
		break;
	case State_Actived:
		colorRole = Color_Border_Actived;
		break;
	case State_Hovered:
		colorRole = Color_Border_Hovered;
		break;
	case State_Pressed:
		colorRole = Color_Border_Pressed;
		break;
	case State_Disable:
		colorRole = Color_Border_Disable;
		break;
	default:
		return;
	}
	if (checked)
	{
		colorRole = Color_Border_Checked;
	}
	if (!setColor(colorRole))
		return;
	if (IRound* round = widget_member(member.widget)->round)
	{
		//glEnable(GL_POLYGON_SMOOTH);
		fillTriangles(round->borderPoints);
		//glDisable(GL_POLYGON_SMOOTH);
	}
	else
	{
		int w = member.widget->width();
		int h = member.widget->height();
		fillRect(0, b, b, h - b - b);
		fillRect(0, 0, w, b);
		fillRect(w - b, b, b, h - b - b);
		fillRect(0, h - b, w, b);
	}
}
void BPainter::drawTitle(State state, bool checked)
{
	if (!member.widget || !member.style)
		return;

	const BRect& titleRect = member.widget->rect(Part_Title);
	if (titleRect.empty())
		return;

	if (!member.state->enabled)
		state = State_Disable;
	if (!state && member.state->actived)
		state = State_Actived;
	if (!state)
		state = State_Normal;

	StyleRole colorRole = Style_None;
	StyleRole imageRole = Style_None;
	switch (state)
	{
	case State_Normal:
		colorRole = Color_Title;
		imageRole = Image_Title;
		break;
	case State_Actived:
		colorRole = Color_Title_Actived;
		imageRole = Image_Title_Actived;
		break;
	case State_Hovered:
		colorRole = Color_Title_Hovered;
		imageRole = Image_Title_Hovered;
		break;
	case State_Pressed:
		colorRole = Color_Title_Pressed;
		imageRole = Image_Title_Pressed;
		break;
	case State_Disable:
		colorRole = Color_Title_Disable;
		imageRole = Image_Title_Disable;
		break;
	default:
		return;
	}

	if(setColor(colorRole))
		fillRect(titleRect);

	if (BImage* image = member.state->style->image(imageRole))
		drawImage(titleRect, image);

}
